﻿using Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Utils;

namespace WpfTreeDemo
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        #region 变量
        private List<PtOrgInfo> orgListAll = new List<PtOrgInfo>();
        private List<PtCameraInfo> cameraListAll = new List<PtCameraInfo>();
        private List<TreeNodeData<PtOrgInfo>> orgNodeDataListFlat = new List<TreeNodeData<PtOrgInfo>>();
        private List<TreeNodeData<PtCameraInfo>> cameraNodeDataList = new List<TreeNodeData<PtCameraInfo>>();
        #endregion

        #region 构造函数
        public MainWindow()
        {
            InitializeComponent();
        }
        #endregion

        #region Window_Loaded
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            ShowOrgCameraTree();
        }
        #endregion

        #region Log
        private void Log(string log)
        {
            this.Dispatcher.InvokeAsync(() =>
            {
                txt.AppendText(DateTime.Now.ToString("HH:mm:ss.fff") + " " + log + "\r\n");
                txt.ScrollToEnd();
            });
        }
        #endregion

        // ==== 组织机构摄像机树 ========================================================================================

        #region ShowOrgCameraTree 显示组织机构摄像机树
        /// <summary>
        /// 显示组织机构摄像机树
        /// </summary>
        private void ShowOrgCameraTree(bool bigData = false)
        {
            DateTime dt = DateTime.Now;
            DateTime startTime = DateTime.Now;
            orgListAll = new List<PtOrgInfo>();
            cameraListAll = new List<PtCameraInfo>();
            orgNodeDataListFlat = new List<TreeNodeData<PtOrgInfo>>();
            cameraNodeDataList = new List<TreeNodeData<PtCameraInfo>>();
            ObservableCollection<TreeNodeData<PtOrgInfo>> orgNodeDataList = null;
            this.orgTree.LoadTree(new ObservableCollection<Models.TreeNodeData<Models.PtOrgInfo>>());
            this.orgTree.loadingWait.Visibility = Visibility.Visible;
            Log("============================================================");

            BackWork.RunAsync(() =>
            {
                #region 生成组织机构和摄像机测试数据
                Random rnd = new Random();

                int countI = 20;
                int countJ = 20;
                int countK = 20;

                for (int i = 0; i < countI; i++)
                {
                    long codeI = 10 + i;

                    PtOrgInfo orgI = new PtOrgInfo();
                    orgI.id = codeI;
                    orgI.parId = -1;
                    orgI.orgName = "测试机构" + codeI;
                    orgI.orgLevel = 0;
                    orgListAll.Add(orgI);

                    for (int j = 0; j < countJ; j++)
                    {
                        long codeJ = codeI * 100 + (j + 1);

                        PtOrgInfo orgJ = new PtOrgInfo();
                        orgJ.id = codeJ;
                        orgJ.parId = codeI;
                        orgJ.orgName = "测试机构" + codeJ;
                        orgJ.orgLevel = 1;
                        orgListAll.Add(orgJ);

                        for (int k = 0; k < countK; k++)
                        {
                            long codeK = codeJ * 100 + (k + 1);

                            PtOrgInfo orgK = new PtOrgInfo();
                            orgK.id = codeK;
                            orgK.parId = codeJ;
                            orgK.orgName = "测试机构" + codeK;
                            orgK.orgLevel = 2;
                            orgListAll.Add(orgK);

                            int countCamera;
                            if (i == 0 && j == 0 && k < 2)
                            {
                                countCamera = 105;
                            }
                            else
                            {
                                countCamera = rnd.Next(1, 50);
                            }
                            if (bigData) countCamera = rnd.Next(135, 180);

                            for (int x = 0; x < countCamera; x++)
                            {
                                string cameraId = (codeK * 1000 + (x + 1)).ToString();

                                PtCameraInfo camera = new PtCameraInfo();
                                camera.ID = cameraId;
                                camera.ORG_ID = orgK.id;
                                camera.CAMERA_NAME = "测试像机" + cameraId;
                                camera.SHORT_MSG = camera.CAMERA_NAME;
                                camera.CAMERA_TYPE = rnd.Next(1, 6);
                                camera.CAMERA_STATE = rnd.Next(0, 2).ToString();
                                cameraListAll.Add(camera);
                            }
                        }
                    }
                }
                #endregion

                string timeStr = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                this.Dispatcher.InvokeAsync(() =>
                {
                    Log("第1步，生成测试数据耗时：" + timeStr + " 秒");
                    Log("组织机构总数：" + orgListAll.Count + "，摄像机总数：" + cameraListAll.Count);
                });
                dt = DateTime.Now;

                orgNodeDataList = new ObservableCollection<TreeNodeData<PtOrgInfo>>(CreateNodeData(orgListAll, cameraListAll, out orgNodeDataListFlat, out cameraNodeDataList)); //生成树节点数据

                timeStr = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                this.Dispatcher.InvokeAsync(() =>
                {
                    Log("第2步，生成节点数据耗时：" + timeStr + " 秒");
                });
                dt = DateTime.Now;
            }, () =>
            {
                this.orgTree.LoadTree(orgNodeDataList);

                SetCameraCount(orgNodeDataListFlat, orgListAll, cameraNodeDataList); //设置在摄像机离线数量

                string timeStr = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("第3步，绑定树节点耗时：" + timeStr + " 秒");
                timeStr = DateTime.Now.Subtract(startTime).TotalSeconds.ToString("0.000");
                Log("总耗时：" + timeStr + " 秒");
            }, ex =>
            {
                Log(ex.Message + "\r\n" + ex.StackTrace);
            });
        }
        #endregion

        #region CreateNodeData 创建树节点
        /// <summary>
        /// 创建树节点
        /// </summary>
        private List<TreeNodeData<PtOrgInfo>> CreateNodeData(List<PtOrgInfo> orgListAll, List<PtCameraInfo> cameraListAll, out List<TreeNodeData<PtOrgInfo>> orgNodeDataListFlat, out List<TreeNodeData<PtCameraInfo>> cameraNodeDataList)
        {
            //组织机构节点集合
            List<TreeNodeData<PtOrgInfo>> orgNodeDataList = orgListAll.ConvertAll(org =>
            {
                TreeNodeData<PtOrgInfo> nodeData = new TreeNodeData<PtOrgInfo>(org);
                nodeData.IsCheckable = true;
                return nodeData;
            });

            //摄像机节点集合
            cameraNodeDataList = cameraListAll.ConvertAll(camera =>
            {
                TreeNodeData<PtCameraInfo> nodeData = new TreeNodeData<PtCameraInfo>(camera);
                nodeData.IsOnline = camera.CAMERA_STATE == "1" ? true : false;
                nodeData.IsCheckable = true;
                return nodeData;
            });

            //组织机构节点字典
            Dictionary<long, TreeNodeData<PtOrgInfo>> dictOrgListAll = orgNodeDataList.ToLookup(item => item.Info.id).ToDictionary(item => item.Key, item => item.First());

            //遍历摄像机节点集合
            foreach (TreeNodeData<PtCameraInfo> cameraNodeData in cameraNodeDataList.ToList())
            {
                long cameraOrgId = Convert.ToInt64(cameraNodeData.Info.ORG_ID);
                if (dictOrgListAll.ContainsKey(cameraOrgId))
                {
                    TreeNodeData<PtOrgInfo> parentNodeData = dictOrgListAll[cameraOrgId];
                    parentNodeData.IsOrgLeaf = true;
                    cameraNodeData.Parent = parentNodeData;
                    if (parentNodeData.Children.Count < cameraNodeData.PageSize)
                    {
                        parentNodeData.Children.Add(cameraNodeData);
                    }
                    parentNodeData.CameraNodeDataList.Add(cameraNodeData);
                    parentNodeData.CameraCount = parentNodeData.CameraNodeDataList.Count;
                }
            }

            //遍历组织机构节点集合
            foreach (TreeNodeData<PtOrgInfo> orgNodeData in orgNodeDataList.ToList())
            {
                if (orgNodeData.Info.parId > 0)
                {
                    if (dictOrgListAll.ContainsKey(orgNodeData.Info.parId))
                    {
                        TreeNodeData<PtOrgInfo> parentNodeData = dictOrgListAll[orgNodeData.Info.parId];
                        orgNodeData.Parent = parentNodeData;
                        parentNodeData.Children.Add(orgNodeData);
                    }
                }
            }

            orgNodeDataListFlat = orgNodeDataList;
            return orgNodeDataList.FindAll(nodeData => nodeData.Info.parId == -1);
        }
        #endregion

        #region SetCameraCount 显示组织机构下的像机总数
        /// <summary>
        /// 显示组织机构下的像机总数
        /// </summary>
        private void SetCameraCount(List<TreeNodeData<PtOrgInfo>> orgNodeDataList, List<PtOrgInfo> orgListAll, List<TreeNodeData<PtCameraInfo>> cameraNodeDataList)
        {
            int _buildPeroid = 0;
            int _treeType = 1;

            Dictionary<long, int> dictCameraCount;
            Dictionary<long, int> dictOnlineCameraCount;
            GetCameraCountDict(orgListAll, cameraNodeDataList, out dictCameraCount, out dictOnlineCameraCount);

            if (_buildPeroid == 0)
            {
                if (_treeType == 1)
                {
                    Dictionary<long, int> dicCameraCount = dictCameraCount;
                    Dictionary<long, int> dicOnlineCameraCount = dictOnlineCameraCount;

                    foreach (TreeNodeData<PtOrgInfo> orgNodeData in orgNodeDataList)
                    {
                        PtOrgInfo org = orgNodeData.Info as PtOrgInfo;

                        int nOnline;
                        int nCount;
                        if (dicCameraCount.TryGetValue(org.id, out nCount) && dicOnlineCameraCount.TryGetValue(org.id, out nOnline))
                        {
                            orgNodeData.CameraCount = nCount;
                            orgNodeData.CameraCountString = string.Format("({0}/{1})", nOnline, nCount);
                        }
                    }
                }
                else
                {
                    foreach (TreeNodeData<PtOrgInfo> orgNodeData in orgNodeDataList)
                    {
                        PtOrgInfo org = orgNodeData.Info as PtOrgInfo;

                        int nOnline;
                        int nCount;
                        dictCameraCount.TryGetValue(org.id, out nCount);
                        dictOnlineCameraCount.TryGetValue(org.id, out nOnline);
                        orgNodeData.CameraCount = nCount;
                        orgNodeData.CameraCountString = string.Format("({0}/{1})", nOnline, nCount);
                    }
                }
            }
            else
            {
                foreach (TreeNodeData<PtOrgInfo> orgNodeData in orgNodeDataList)
                {
                    PtOrgInfo org = orgNodeData.Info as PtOrgInfo;

                    int nOnline;
                    int nCount;
                    dictCameraCount.TryGetValue(org.id, out nCount);
                    dictOnlineCameraCount.TryGetValue(org.id, out nOnline);
                    orgNodeData.CameraCount = nCount;
                    orgNodeData.CameraCountString = string.Format("({0}/{1})", nOnline, nCount);
                }
            }
        }

        #endregion 显示组织机构下的像机总数

        #region GetCameraCountDict 计算所有组织机构下的像机数

        /// <summary>
        /// 计算所有组织机构下的像机数
        /// </summary>
        private void GetCameraCountDict(List<PtOrgInfo> orgListAll, List<TreeNodeData<PtCameraInfo>> cameraNodeDataList, out Dictionary<long, int> dictCameraCount, out Dictionary<long, int> dictOnlineCameraCount)
        {
            int _treeType = 1;
            List<PtCameraInfo> cameraListAll = cameraNodeDataList.ConvertAll<PtCameraInfo>(a => a.Info);

            dictCameraCount = new Dictionary<long, int>();
            dictOnlineCameraCount = new Dictionary<long, int>();

            //组织机构字典
            Dictionary<long, PtOrgInfo> dictOrgListAll = orgListAll.ToLookup(item => item.id).ToDictionary(item => item.Key, item => item.First());
            Dictionary<string, PtOrgInfo> dictOrgListAllByOrgName = orgListAll.ToLookup(item => item.orgName).ToDictionary(item => item.Key, item => item.First());

            //初始化数据
            foreach (PtOrgInfo orgInfo in orgListAll)
            {
                dictCameraCount.Add(orgInfo.id, 0);
                dictOnlineCameraCount.Add(orgInfo.id, 0);
            }

            //遍历所有父级组织机构，像机数+1
            Action<PtOrgInfo, Dictionary<long, int>> action = null;
            action = (PtOrgInfo orgInfo, Dictionary<long, int> dict) =>
            {
                PtOrgInfo parentOrg;
                if (dictOrgListAll.TryGetValue(orgInfo.parId, out parentOrg))
                {
                    dict[parentOrg.id]++;
                    action(parentOrg, dict);
                }
            };

            if (_treeType == 5) cameraListAll = cameraListAll.FindAll(a => a.RECODE_SAVE_TYPE == 2 && a.BuildPeriod == 2);

            foreach (TreeNodeData<PtCameraInfo> cameraNodeData in cameraNodeDataList)
            {
                long orgId = -1;
                PtCameraInfo cameraInfo = cameraNodeData.Info;

                if (cameraInfo.ORG_ID.HasValue && cameraNodeData.IsVisible)
                {
                    if (_treeType == 1)
                    {
                        orgId = (long)cameraInfo.ORG_ID.Value;
                    }
                    if (_treeType == 2)
                    {
                        orgId = (long)cameraInfo.KeyUnit;
                    }
                    if (_treeType == 3)
                    {
                        if (!string.IsNullOrWhiteSpace(cameraInfo.Street))
                        {
                            PtOrgInfo orgInfo;
                            if (dictOrgListAllByOrgName.TryGetValue(cameraInfo.Street, out orgInfo))
                            {
                                orgId = orgInfo.id;
                            }
                        }
                    }
                    if (_treeType == 5)
                    {
                        orgId = (long)cameraInfo.ORG_ID.Value;
                    }
                }

                if (orgId > 0)
                {
                    if (dictCameraCount.ContainsKey(orgId))
                    {
                        dictCameraCount[orgId]++;
                    }
                    else
                    {
                        dictCameraCount.Add(orgId, 1);
                    }
                    PtOrgInfo orgInfo;
                    if (dictOrgListAll.TryGetValue(orgId, out orgInfo))
                    {
                        action(orgInfo, dictCameraCount);
                    }
                }

                if (orgId > 0 && cameraInfo.CAMERA_STATE == "1")
                {
                    if (dictOnlineCameraCount.ContainsKey(orgId))
                    {
                        dictOnlineCameraCount[orgId]++;
                    }
                    else
                    {
                        dictOnlineCameraCount.Add(orgId, 1);
                    }
                    PtOrgInfo orgInfo;
                    if (dictOrgListAll.TryGetValue(orgId, out orgInfo))
                    {
                        action(orgInfo, dictOnlineCameraCount);
                    }
                }
            }
        }

        #endregion 计算所有组织机构下的像机数

        // ==== 按钮事件 ================================================================================================

        #region btnReloadTree_Click 重新生成树
        private void btnReloadTree_Click(object sender, RoutedEventArgs e)
        {
            ShowOrgCameraTree();
        }
        #endregion

        #region btnSelectedCameras_Click 获取选择的摄像机集合
        private void btnSelectedCameras_Click(object sender, RoutedEventArgs e)
        {
            DateTime dt = DateTime.Now;
            List<PtCameraInfo> list = this.orgTree.GetSelectedCameras();
            if (list.Count > 0)
            {
                StringBuilder sbCameras = new StringBuilder();
                list.ForEach(item =>
                {
                    sbCameras.Append("，" + item.CAMERA_NAME);
                });
                Log(sbCameras.ToString(1, sbCameras.Length - 1));
                string timeStr = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("选择的摄像机总数：" + list.Count);
                Log("获取选择的摄像机集合耗时：" + timeStr + " 秒\r\n");
            }
            else
            {
                Log("选择的摄像机总数：" + list.Count);
            }
        }
        #endregion

        #region btnSelectedOrgs_Click 获取选择的组织机构集合
        private void btnSelectedOrgs_Click(object sender, RoutedEventArgs e)
        {
            DateTime dt = DateTime.Now;
            List<PtOrgInfo> list = this.orgTree.GetSelectedOrgs();
            if (list.Count > 0)
            {
                StringBuilder sbCameras = new StringBuilder();
                list.ForEach(item =>
                {
                    sbCameras.Append("，" + item.orgName);
                });
                Log(sbCameras.ToString(1, sbCameras.Length - 1));
                string timeStr = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("选择的组织机构总数：" + list.Count);
                Log("获取选择的组织机构集合耗时：" + timeStr + " 秒\r\n");
            }
            else
            {
                Log("选择的组织机构总数：" + list.Count);
            }
        }
        #endregion

        #region btnSearch_Click 搜索
        private void btnSearch_Click(object sender, RoutedEventArgs e)
        {
            DateTime dt = DateTime.Now;
            this.orgTree.Search(txtSearchKey.Text.Trim());
            SetCameraCount(orgNodeDataListFlat, orgListAll, cameraNodeDataList); //设置摄像机在离线数量
            string timeStr = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
            Log("搜索耗时：" + timeStr + " 秒");
        }
        #endregion

        #region btnReloadTree_Click 重新生成树(较大数据量)
        private void btnReloadTreeBigData_Click(object sender, RoutedEventArgs e)
        {
            ShowOrgCameraTree(true);
        }
        #endregion

    }
}
